home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / linux / atari / source / source.lzh / atari-linux-0.01pl3 / drivers / block / ll_rw_blk.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-19  |  11.8 KB  |  495 lines

  1. /*
  2.  *  linux/kernel/blk_dev/ll_rw.c
  3.  *
  4.  * Copyright (C) 1991, 1992 Linus Torvalds
  5.  *
  6.  * This file is subject to the terms and conditions of the GNU General Public
  7.  * License.  See the file README.legal in the main directory of this archive
  8.  * for more details.
  9.  */
  10.  
  11. /*
  12.  * This handles all read/write requests to block devices
  13.  */
  14. #include <linux/sched.h>
  15. #include <linux/kernel.h>
  16. #include <linux/errno.h>
  17. #include <linux/string.h>
  18. #include <linux/config.h>
  19. #include <linux/locks.h>
  20.  
  21. #include <linux/bootinfo.h>
  22.  
  23. #include <asm/system.h>
  24.  
  25. #include "blk.h"
  26.  
  27. /*
  28.  * The request-struct contains all necessary data
  29.  * to load a nr of sectors into memory
  30.  */
  31. static struct request all_requests[NR_REQUEST];
  32.  
  33. /*
  34.  * used to wait on when there are no free requests
  35.  */
  36. struct wait_queue * wait_for_request = NULL;
  37.  
  38. /* This specifies how many sectors to read ahead on the disk.  */
  39.  
  40. int read_ahead[MAX_BLKDEV] = {0, };
  41.  
  42. /* blk_dev_struct is:
  43.  *    do_request-address
  44.  *    next-request
  45.  */
  46. struct blk_dev_struct blk_dev[MAX_BLKDEV] = {
  47.     { NULL, NULL },     /* no_dev */
  48.     { NULL, NULL },     /* dev mem */
  49.     { NULL, NULL },     /* dev fd */
  50.     { NULL, NULL },     /* dev hd */
  51.     { NULL, NULL },     /* dev ttyx */
  52.     { NULL, NULL },     /* dev tty */
  53.     { NULL, NULL },     /* dev lp */
  54.     { NULL, NULL },     /* dev pipes */
  55.     { NULL, NULL },     /* dev sd */
  56.     { NULL, NULL }        /* dev st */
  57. };
  58.  
  59. /*
  60.  * blk_size contains the size of all block-devices in units of 1024 byte
  61.  * sectors:
  62.  *
  63.  * blk_size[MAJOR][MINOR]
  64.  *
  65.  * if (!blk_size[MAJOR]) then no minor size checking is done.
  66.  */
  67. int * blk_size[MAX_BLKDEV] = { NULL, NULL, };
  68.  
  69. /*
  70.  * blksize_size contains the size of all block-devices:
  71.  *
  72.  * blksize_size[MAJOR][MINOR]
  73.  *
  74.  * if (!blksize_size[MAJOR]) then 1024 bytes is assumed.
  75.  */
  76. int * blksize_size[MAX_BLKDEV] = { NULL, NULL, };
  77.  
  78. /*
  79.  * look for a free request in the first N entries.
  80.  * NOTE: interrupts must be disabled on the way in, and will still
  81.  *       be disabled on the way out.
  82.  */
  83. static inline struct request * get_request(int n, int dev)
  84. {
  85.     static struct request *prev_found = NULL, *prev_limit = NULL;
  86.     register struct request *req, *limit;
  87.  
  88.     if (n <= 0)
  89.         panic("get_request(%d): impossible!\n", n);
  90.  
  91.     limit = all_requests + n;
  92.     if (limit != prev_limit) {
  93.         prev_limit = limit;
  94.         prev_found = all_requests;
  95.     }
  96.     req = prev_found;
  97.     for (;;) {
  98.         req = ((req > all_requests) ? req : limit) - 1;
  99.         if (req->dev < 0)
  100.             break;
  101.         if (req == prev_found)
  102.             return NULL;
  103.     }
  104.     prev_found = req;
  105.     req->dev = dev;
  106.     return req;
  107. }
  108.  
  109. /*
  110.  * wait until a free request in the first N entries is available.
  111.  * NOTE: interrupts must be disabled on the way in, and will still
  112.  *       be disabled on the way out.
  113.  */
  114. static inline struct request * get_request_wait(int n, int dev)
  115. {
  116.     register struct request *req;
  117.  
  118.     while ((req = get_request(n, dev)) == NULL)
  119.         sleep_on(&wait_for_request);
  120.     return req;
  121. }
  122.  
  123. /* RO fail safe mechanism */
  124.  
  125. static long ro_bits[MAX_BLKDEV][8];
  126.  
  127. int is_read_only(int dev)
  128. {
  129.     int minor,major;
  130.  
  131.     major = MAJOR(dev);
  132.     minor = MINOR(dev);
  133.     if (major < 0 || major >= MAX_BLKDEV) return 0;
  134.     return ro_bits[major][minor >> 5] & (1 << (minor & 31));
  135. }
  136.  
  137. void set_device_ro(int dev,int flag)
  138. {
  139.     int minor,major;
  140.  
  141.     major = MAJOR(dev);
  142.     minor = MINOR(dev);
  143.     if (major < 0 || major >= MAX_BLKDEV) return;
  144.     if (flag) ro_bits[major][minor >> 5] |= 1 << (minor & 31);
  145.     else ro_bits[major][minor >> 5] &= ~(1 << (minor & 31));
  146. }
  147.  
  148. /*
  149.  * add-request adds a request to the linked list.
  150.  * It disables interrupts so that it can muck with the
  151.  * request-lists in peace.
  152.  */
  153. static void add_request(struct blk_dev_struct * dev, struct request * req)
  154. {
  155.     struct request * tmp;
  156.  
  157.     req->next = NULL;
  158.     cli();
  159.     if (req->bh)
  160.         req->bh->b_dirt = 0;
  161.     if (!(tmp = dev->current_request)) {
  162.         dev->current_request = req;
  163.         (dev->request_fn)();
  164.         sti();
  165.         return;
  166.     }
  167.     for ( ; tmp->next ; tmp = tmp->next) {
  168.         if ((IN_ORDER(tmp,req) ||
  169.             !IN_ORDER(tmp,tmp->next)) &&
  170.             IN_ORDER(req,tmp->next))
  171.             break;
  172.     }
  173.     req->next = tmp->next;
  174.     tmp->next = req;
  175.  
  176. /* for SCSI devices, call request_fn unconditionally */
  177.     if (scsi_major(MAJOR(req->dev)))
  178.         (dev->request_fn)();
  179.  
  180.     sti();
  181. }
  182.  
  183. static void make_request(int major,int rw, struct buffer_head * bh)
  184. {
  185.     unsigned int sector, count;
  186.     struct request * req;
  187.     int rw_ahead, max_req;
  188.  
  189. /* WRITEA/READA is special case - it is not really needed, so if the */
  190. /* buffer is locked, we just forget about it, else it's a normal read */
  191.     rw_ahead = (rw == READA || rw == WRITEA);
  192.     if (rw_ahead) {
  193.         if (bh->b_lock)
  194.             return;
  195.         if (rw == READA)
  196.             rw = READ;
  197.         else
  198.             rw = WRITE;
  199.     }
  200.     if (rw!=READ && rw!=WRITE) {
  201.         printk("Bad block dev command, must be R/W/RA/WA\n");
  202.         return;
  203.     }
  204.     count = bh->b_size >> 9;
  205.     sector = bh->b_blocknr * count;
  206.     if (blk_size[major])
  207.         if (blk_size[major][MINOR(bh->b_dev)] < (sector + count)>>1) {
  208.             bh->b_dirt = bh->b_uptodate = 0;
  209.             return;
  210.         }
  211.     lock_buffer(bh);
  212.     if ((rw == WRITE && !bh->b_dirt) || (rw == READ && bh->b_uptodate)) {
  213.         unlock_buffer(bh);
  214.         return;
  215.     }
  216.  
  217. /* we don't allow the write-requests to fill up the queue completely:
  218.  * we want some room for reads: they take precedence. The last third
  219.  * of the requests are only for reads.
  220.  */
  221.     max_req = (rw == READ) ? NR_REQUEST : ((NR_REQUEST*2)/3);
  222.  
  223. /* big loop: look for a free request. */
  224.  
  225. repeat:
  226.     cli();
  227.  
  228. /* The scsi disk drivers completely remove the request from the queue when
  229.  * they start processing an entry.  For this reason it is safe to continue
  230.  * to add links to the top entry for scsi devices.
  231.  */
  232.     if ((major == HD_MAJOR
  233.          || major == SCSI_DISK_MAJOR
  234.          || major == SCSI_CDROM_MAJOR)
  235.         && (req = blk_dev[major].current_request))
  236.     {
  237.             if (major == HD_MAJOR)
  238.             req = req->next;
  239.         while (req) {
  240.             if (req->dev == bh->b_dev &&
  241.                 !req->waiting &&
  242.                 req->cmd == rw &&
  243.                 req->sector + req->nr_sectors == sector &&
  244.                 req->nr_sectors < 254)
  245.             {
  246.                 req->bhtail->b_reqnext = bh;
  247.                 req->bhtail = bh;
  248.                 req->nr_sectors += count;
  249.                 bh->b_dirt = 0;
  250.                 sti();
  251.                 return;
  252.             }
  253.  
  254.             if (req->dev == bh->b_dev &&
  255.                 !req->waiting &&
  256.                 req->cmd == rw &&
  257.                 req->sector - count == sector &&
  258.                 req->nr_sectors < 254)
  259.                 {
  260.                     req->nr_sectors += count;
  261.                     bh->b_reqnext = req->bh;
  262.                     req->buffer = bh->b_data;
  263.                     req->current_nr_sectors = count;
  264.                     req->sector = sector;
  265.                     bh->b_dirt = 0;
  266.                     req->bh = bh;
  267.                     sti();
  268.                     return;
  269.             }    
  270.  
  271.             req = req->next;
  272.         }
  273.     }
  274.  
  275. /* find an unused request. */
  276.     req = get_request(max_req, bh->b_dev);
  277.  
  278. /* if no request available: if rw_ahead, forget it; otherwise try again. */
  279.     if (! req) {
  280.         if (rw_ahead) {
  281.             sti();
  282.             unlock_buffer(bh);
  283.             return;
  284.         }
  285.         sleep_on(&wait_for_request);
  286.         sti();
  287.         goto repeat;
  288.     }
  289.  
  290. /* we found a request. */
  291.     sti();
  292.  
  293. /* fill up the request-info, and add it to the queue */
  294.     req->cmd = rw;
  295.     req->errors = 0;
  296.     req->sector = sector;
  297.     req->nr_sectors = count;
  298.     req->current_nr_sectors = count;
  299.     req->buffer = bh->b_data;
  300.     req->waiting = NULL;
  301.     req->bh = bh;
  302.     req->bhtail = bh;
  303.     req->next = NULL;
  304.     add_request(major+blk_dev,req);
  305. }
  306.  
  307. void ll_rw_page(int rw, int dev, int page, char * buffer)
  308. {
  309.     struct request * req;
  310.     unsigned int major = MAJOR(dev);
  311.  
  312.     if (major >= MAX_BLKDEV || !(blk_dev[major].request_fn)) {
  313.         printk("Trying to read nonexistent block-device %04x (%d)\n",dev,page*8);
  314.         return;
  315.     }
  316.     if (rw!=READ && rw!=WRITE)
  317.         panic("Bad block dev command, must be R/W");
  318.     if (rw == WRITE && is_read_only(dev)) {
  319.         printk("Can't page to read-only device 0x%X\n",dev);
  320.         return;
  321.     }
  322.     cli();
  323.     req = get_request_wait(NR_REQUEST, dev);
  324.     sti();
  325. /* fill up the request-info, and add it to the queue */
  326.     req->cmd = rw;
  327.     req->errors = 0;
  328.     req->sector = page<<3;
  329.     req->nr_sectors = 8;
  330.     req->current_nr_sectors = 8;
  331.     req->buffer = buffer;
  332.     req->waiting = current;
  333.     req->bh = NULL;
  334.     req->next = NULL;
  335.     current->state = TASK_SWAPPING;
  336.     add_request(major+blk_dev,req);
  337.     schedule();
  338. }
  339.  
  340. /* This function can be used to request a number of buffers from a block
  341.    device. Currently the only restriction is that all buffers must belong to
  342.    the same device */
  343.  
  344. void ll_rw_block(int rw, int nr, struct buffer_head * bh[])
  345. {
  346.     unsigned int major;
  347.     struct request plug;
  348.     int plugged;
  349.     int correct_size;
  350.     struct blk_dev_struct * dev;
  351.     int i;
  352.  
  353.     /* Make sure that the first block contains something reasonable */
  354.     while (!*bh) {
  355.         bh++;
  356.         if (--nr <= 0)
  357.             return;
  358.     };
  359.  
  360.     dev = NULL;
  361.     if ((major = MAJOR(bh[0]->b_dev)) < MAX_BLKDEV)
  362.         dev = blk_dev + major;
  363.     if (!dev || !dev->request_fn) {
  364.         printk(
  365.     "ll_rw_block: Trying to read nonexistent block-device %04lX (%ld)\n",
  366.                (unsigned long) bh[0]->b_dev, bh[0]->b_blocknr);
  367.         goto sorry;
  368.     }
  369.  
  370.     /* Determine correct block size for this device.  */
  371.     correct_size = BLOCK_SIZE;
  372.     if (blksize_size[major]) {
  373.         i = blksize_size[major][MINOR(bh[0]->b_dev)];
  374.         if (i)
  375.             correct_size = i;
  376.     }
  377.  
  378.     /* Verify requested block sizees.  */
  379.     for (i = 0; i < nr; i++) {
  380.         if (bh[i] && bh[i]->b_size != correct_size) {
  381.             printk(
  382.             "ll_rw_block: only %d-char blocks implemented (%lu)\n",
  383.                    correct_size, bh[i]->b_size);
  384.             goto sorry;
  385.         }
  386.     }
  387.  
  388.     if ((rw == WRITE || rw == WRITEA) && is_read_only(bh[0]->b_dev)) {
  389.         printk("Can't write to read-only device 0x%X\n",bh[0]->b_dev);
  390.         goto sorry;
  391.     }
  392.  
  393.     /* If there are no pending requests for this device, then we insert
  394.        a dummy request for that device.  This will prevent the request
  395.        from starting until we have shoved all of the blocks into the
  396.        queue, and then we let it rip.  */
  397.  
  398.     plugged = 0;
  399.     cli();
  400.     if (!dev->current_request && nr > 1) {
  401.         dev->current_request = &plug;
  402.         plug.dev = -1;
  403.         plug.next = NULL;
  404.         plugged = 1;
  405.     }
  406.     sti();
  407.     for (i = 0; i < nr; i++) {
  408.         if (bh[i]) {
  409.             bh[i]->b_req = 1;
  410.             make_request(major, rw, bh[i]);
  411.         }
  412.     }
  413.     if (plugged) {
  414.         cli();
  415.         dev->current_request = plug.next;
  416.         (dev->request_fn)();
  417.         sti();
  418.     }
  419.     return;
  420.  
  421.       sorry:
  422.     for (i = 0; i < nr; i++) {
  423.         if (bh[i])
  424.             bh[i]->b_dirt = bh[i]->b_uptodate = 0;
  425.     }
  426.     return;
  427. }
  428.  
  429. void ll_rw_swap_file(int rw, int dev, unsigned int *b, int nb, char *buf)
  430. {
  431.     int i;
  432.     int buffersize;
  433.     struct request * req;
  434.     unsigned int major = MAJOR(dev);
  435.  
  436.     if (major >= MAX_BLKDEV || !(blk_dev[major].request_fn)) {
  437.         printk("ll_rw_swap_file: trying to swap nonexistent block-device\n");
  438.         return;
  439.     }
  440.  
  441.     if (rw!=READ && rw!=WRITE) {
  442.         printk("ll_rw_swap: bad block dev command, must be R/W");
  443.         return;
  444.     }
  445.     if (rw == WRITE && is_read_only(dev)) {
  446.         printk("Can't swap to read-only device 0x%X\n",dev);
  447.         return;
  448.     }
  449.  
  450.     buffersize = PAGE_SIZE / nb;
  451.  
  452.     for (i=0; i<nb; i++, buf += buffersize)
  453.     {
  454.         cli();
  455.         req = get_request_wait(NR_REQUEST, dev);
  456.         sti();
  457.         req->cmd = rw;
  458.         req->errors = 0;
  459.         req->sector = (b[i] * buffersize) >> 9;
  460.         req->nr_sectors = buffersize >> 9;
  461.         req->current_nr_sectors = buffersize >> 9;
  462.         req->buffer = buf;
  463.         req->waiting = current;
  464.         req->bh = NULL;
  465.         req->next = NULL;
  466.         current->state = TASK_UNINTERRUPTIBLE;
  467.         add_request(major+blk_dev,req);
  468.         schedule();
  469.     }
  470. }
  471.  
  472. long blk_dev_init(long mem_start, long mem_end)
  473. {
  474.     struct request * req;
  475.  
  476.     req = all_requests + NR_REQUEST;
  477.     while (--req >= all_requests) {
  478.         req->dev = -1;
  479.         req->next = NULL;
  480.     }
  481.     memset(ro_bits,0,sizeof(ro_bits));
  482. #if defined(CONFIG_BLK_DEV_HD) || defined(CONFIG_AMIGA_IDE) || defined(CONFIG_ATARI_FALCON_IDE)
  483.     mem_start = hd_init(mem_start,mem_end);
  484. #endif
  485. #ifdef CONFIG_CDU31A
  486.     mem_start = cdu31a_init(mem_start,mem_end);
  487. #endif
  488. #ifdef CONFIG_MCD
  489.     mem_start = mcd_init(mem_start,mem_end);
  490. #endif
  491.     if (boot_info.ramdisk_size)
  492.         mem_start += rd_init(mem_start, boot_info.ramdisk_size*1024);
  493.     return mem_start;
  494. }
  495.